(ns ca.uoit.molly.web.core
  (:use compojure.core
        ring.adapter.jetty
        ca.uoit.molly.lucene-helper
        ca.uoit.molly.search-api
        clojure.data.json)
  (:require [compojure.route :as route])
  (:require [compojure.handler :as handler]))

(defn jsonp?
  "Returns true if a callback function exists, false if it does not."
  [callback]
  (not-empty callback))

(defn jsonify
  [data]
  (json-str {:data data}))

(defn jsonpify
  [data callback]
  (str callback "(" (jsonify data) ")"))

(defn ret-js
  "Returns JavaScript in either JSON or JSONP form, depending on whether or not
    a callback is specified.  It should automagically specify the correct header
    information as well as body content."
  [data callback]
  (let [jsonp (jsonp? callback)]
    {:status 200
     :headers {"Content-Type"
               (if jsonp
                 "application/javascript"
                 "application/json")}
     :body
        (if jsonp
          (jsonpify data callback)
          (jsonify data))}))

(defn reasonable-topk?
  [topk]
  (<= topk 50))

(defn topk-or-default
  [k]
  (if (empty? k)
    25
    (Integer/parseInt k)))

;Currently broken.
(def *erroneous-reply*
  {:status 400
   :headers {"Content-Type" "text/html"}
   :body (str "<p>There was a problem handling your request.  Please ensure "
      "all parameters have been correctly specified.</p>")})

(def *searcher*
  {:entity (mk-index-searcher "mycampus-entity.idx")
    :value (mk-index-searcher "mycampus-value.idx")})

(defroutes main-routes
  (GET "/entity/"
    [q callback topk]
    (let [k (topk-or-default topk)]
      (if (reasonable-topk? k)
        (ret-js (search-entities (:entity *searcher*) k q) callback)
        *erroneous-reply*)))
  (POST "/entity/"
    ; Absolutely no validation is performed, probably a bad idea.
    [constraints callback topk]
    (let [k (topk-or-default topk)]
      (println (read-json constraints))
      (ret-js (search-entities (:entity *searcher*) k "" (read-json constraints)) callback)))
  (GET "/value/"
    [q callback topk]
      (let [k (topk-or-default topk)]
        (if (reasonable-topk? k)
          (ret-js (search-values (:value *searcher*) k q) callback)
          *erroneous-reply*)))
  (route/not-found "not found"))

(def *app*
  (handler/site main-routes))

(run-jetty *app* {:port 8000})